package com.yc.mypredictefactory;

import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

/**
 * 自定义路由断言工厂，用于根据设备类型（PC/Mobile）进行路由判断
 * postman测试:
 * get请求 url: localhost:20001/go/hello
 * 	Header:  添加 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)         -》Hello from PC!
 * 		    User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X)  -》Hello from Mobile!
 */
@Component
public class DeviceRoutePredicateFactory extends AbstractRoutePredicateFactory<DeviceRoutePredicateFactory.Config> {

    /**
     * 构造函数，初始化父类的Config类
     */
    public DeviceRoutePredicateFactory() {
        super(Config.class);
    }

    /**
     * 定义配置参数的快捷字段顺序
     * @return 返回配置参数名称列表（这里只有一个deviceType参数）
     */
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("deviceType"); // 支持配置 deviceType=PC|Mobile
    }

    /**
     * 创建路由断言逻辑
     * @param config 配置对象，包含设备类型配置
     * @return 返回一个断言函数，用于判断请求是否匹配路由条件
     */
    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return exchange -> {
            // 从请求头中获取User-Agent信息
            String userAgent = exchange.getRequest().getHeaders().getFirst("User-Agent");
            if (userAgent == null) return false;

            // 将User-Agent转为小写方便判断
            String ua = userAgent.toLowerCase();

            // 判断是否为手机设备：包含iphone、android或mobile关键字
            boolean isMobile = ua.contains("iphone") || ua.contains("android") || ua.contains("mobile");

            // 根据配置的设备类型返回匹配结果
            if ("Mobile".equalsIgnoreCase(config.getDeviceType())) {
                return isMobile;
            } else if ("PC".equalsIgnoreCase(config.getDeviceType())) {
                return !isMobile;
            }

            return false;
        };
    }

    /**
     * 配置类，用于接收配置文件中的参数
     */
    public static class Config {
        private String deviceType; // 设备类型：PC或Mobile

        public String getDeviceType() {
            return deviceType;
        }

        public void setDeviceType(String deviceType) {
            this.deviceType = deviceType;
        }
    }
}